#!/usr/bin/env ruby

require 'rubygems'
require 'hpricot'
require 'open-uri'

class Weather
  attr_reader :current_temp_f, 
              :current_conditions, 
              :current_img_url,
              :todays_high_f, 
              :todays_conditions,
              :todays_img_url,
              :city_name,
              :more_url
  
  def initialize(zip)
    remote_api_reply = open("http://www.google.com/ig/api?weather=" + zip) {|f| Hpricot.XML(f) }
    weather = remote_api_reply.at('/xml_api_reply/weather')
    @current_temp_f = weather.at('/current_conditions/temp_f')['data']
    @current_conditions = weather.at('/current_conditions/condition')['data']
    @current_img_url = "http://www.google.com" + weather.at('/current_conditions/icon')['data']
    @todays_high_f = weather.search('/forecast_conditions/high').first['data']
    @todays_conditions = weather.search('/forecast_conditions/condition').first['data']    
    @todays_img_url = "http://www.google.com" + weather.search('/forecast_conditions/icon').first['data']
    @city_name = weather.at('/forecast_information/city')['data']
  end
end

class TransitLine
  protected
    # converts comma-separated strings into array of Time objects
    def self.make_times_arr(times_list, offset)
      times_array = times_list.split(',').collect {|time_string| Time.parse(time_string) + (60 * Integer(offset))}
      times_array.sort
    end
  
  public  
    attr_reader :name, :weekday_times, :saturday_times, :sunday_times, :todays_departures
  
    def <=> line
      if (self.next_departure.nil? && line.next_departure.nil?) then
        return 0
      elsif (self.next_departure.nil? && !line.next_departure.nil?) then
        return 1
      elsif (!self.next_departure.nil? && line.next_departure.nil?) then
        return -1
      else
        return self.next_departure <=> line.next_departure
      end      
    end
  
    # constructor takes everything in as strings, keeps all the processing here and out of the XML parser below
    def initialize(name, weekday_times_string, saturday_times_string, sunday_times_string, offset)
      @name = name; # string
    
      @weekday_times = TransitLine.make_times_arr(weekday_times_string, offset) #times are passed in as comma-separated strings, stored as array of Times
      @saturday_times = TransitLine.make_times_arr(saturday_times_string, offset)
      @sunday_times = TransitLine.make_times_arr(sunday_times_string, offset)
      @todays_departures = []
      
      now = Time.now
    
      if (now.wday >= 1 && now.wday <= 5)
        @todays_departures = weekday_times
      elsif (now.wday == 6)
        @todays_departures = saturday_times
      else
        @todays_departures = sunday_times
      end
    end

    def previous_departure
      now = Time.now

      @todays_departures.reverse.each do |time|
        if (time <= now) then
          return time
        end                    
      end          
            
      return nil
    end
    
    def next_departure
      now = Time.now

      @todays_departures.each do |time|
        if (time > now) then
          return time
        end                    
      end          
            
      return nil
    end
    
    def future_departure
      now = Time.now

      @todays_departures.each_index do |i|
        if (i == @todays_departures.length - 1) then
          return nil
        end
        
        if (@todays_departures[i] > now) then
          return @todays_departures[i+1]
        end                    
      end          

      return nil    
    end
    
    def to_s
      @name
    end
end

class TransitCorridor
  attr_reader :name, :lines
  
  def initialize(name, lines)
    @name = name
    @lines = lines
  end
end

class OutTheDoor
  attr_reader :weather, :transit_corridors
  
  def initialize(config_file)
    config = open(config_file) {|f| Hpricot.XML(f) }
    zip = config.at('/config/location/zip').inner_html
    ENV["TZ"] = config.at('/config/location/timezone').inner_html # kind of a cheat

    # make array of all corridors
    @transit_corridors = config.search('/config/transit_schedule/corridor').collect do |xml_corridor|
      corridor_name = xml_corridor['name']

      # make array of lines for this corridor
      corridor_lines = xml_corridor.search('/line').collect do |xml_line| 
        line_name = xml_line['name']
        offset = xml_line['offset']
        weekday_times = xml_line.at('/weekday_departures').inner_html
        saturday_times = xml_line.at('/saturday_departures').inner_html
        sunday_times = xml_line.at('/sunday_departures').inner_html
    
        TransitLine.new(line_name, weekday_times, saturday_times, sunday_times, offset)
      end
  
      TransitCorridor.new(corridor_name, corridor_lines)
    end

    @weather = Weather.new(zip)
  end
end





 























